#include "SolidworksWriter.hpp"
#include "swwrite/solidworksw.hpp"
#include "./utils/FileUtil.h"

#ifndef CXX_LESS_17
#else
    #include <codecvt>
    #include <locale>
#endif

namespace AMCAX::Exchange
{
    Dtk_ErrorStatus SolidworksWriter::WriteInit(Dtk_string DumpFile, const Dtk_string& inOutputFolder)
    {
        m_outputFileName = inOutputFolder;
        // Dtk_string logwrite = inOutputFolder + L"logwrite.txt";
        auto status = solidworksw::InitWriter(Dtk_string(), NULL, solidworksw::english);

        if (status != dtkNoError)
        {
            std::cout << "error : " << dtkTypeError(status).c_str() << std::endl;
            return status;
        }
        return status;
    }

    Dtk_ErrorStatus SolidworksWriter::WriteEnd()
    {
        auto status = solidworksw::EndWriter();
        if (status != dtkNoError)
        {
            std::cout << "error : " << dtkTypeError(status).c_str() << std::endl;
        }
        else
            std::cout << "=> " << m_outputFileName.c_str() << std::endl;

        return status;
    }

    Dtk_ErrorStatus SolidworksWriter::CreateAssembly(Dtk_ComponentPtr inComponent, Dtk_ID& outAssemblyId)
    {
        return dtkNoError;
    }

    Dtk_ErrorStatus SolidworksWriter::CloseAssembly(const Dtk_ComponentPtr& inComponent)
    {
        return dtkNoError;
    }

    void SolidworksWriter::InitComponent(Dtk_ComponentPtr inComponent)
    {
        if (!inComponent)
            return;
        auto componentName = inComponent->Name();
        if (!inComponent->IsAssembly())
        {
#ifndef CXX_LESS_17
            std::filesystem::path filePath = WriterBase::GetWStringFromDtkString(m_outputFileName);
            auto parentDir = filePath.parent_path();
            Dtk_string fileName = componentName + L".sldprt";
            std::filesystem::path file = WriterBase::GetWStringFromDtkString(fileName);
            filePath = (parentDir.lexically_normal() / file.lexically_normal());
#else
            std::wstring filePath = WriterBase::GetWStringFromDtkString(m_outputFileName);
            std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
            std::string temp = conv.to_bytes(filePath);
            auto parentDir = FileUtil::GetParentPath(temp) ;
            Dtk_string fileName = componentName + L".sldprt";
            temp = conv.to_bytes(WriterBase::GetWStringFromDtkString(fileName));
            std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converteToWide;
            temp = parentDir + "/" + temp ;
            filePath =  converteToWide.from_bytes(temp);
#endif
            OpenPart(filePath.c_str());
        }
    }

    void SolidworksWriter::EndComponent(Dtk_ComponentPtr inComponent)
    {
        if (!inComponent)
            return;

        auto componentName = inComponent->Name();
        if (!inComponent->IsAssembly())
        {
            ClosePart();
        }
    }

    void SolidworksWriter::WriteMetaData(const Dtk_MetaDataPtr& inMetaData)
    {
        auto status = solidworksw::AddMetaData(inMetaData);
        if (status != dtkNoError)
        {
            std::cout << "error : " << dtkTypeError(status).c_str() << std::endl;
        }
    }

    void SolidworksWriter::WriteMesh(Dtk_MeshPtr& inMeshToWrite, Dtk_tab<Dtk_ID>& outIds)
    {
        auto status = solidworksw::AddEntity(Dtk_EntityPtr::DtkDynamicCast(inMeshToWrite));
        if (status != dtkNoError)
        {
            std::cout << "error : " << dtkTypeError(status).c_str() << std::endl;
        }
    }

    void SolidworksWriter::WriteBody(Dtk_BodyPtr& inBody, Dtk_tab<Dtk_ID>& outIds)
    {
        auto status = solidworksw::AddEntity(Dtk_EntityPtr::DtkDynamicCast(inBody));
        if (status != dtkNoError)
        {
            std::cout << "error : " << dtkTypeError(status).c_str() << std::endl;
        }
    }

    void SolidworksWriter::WriteAxisSystem(const Dtk_AxisSystemPtr& inAxis)
    {
        auto status = solidworksw::AddEntity(Dtk_EntityPtr::DtkDynamicCast(inAxis));
        if (status != dtkNoError)
        {
            std::cout << "error : " << dtkTypeError(status).c_str() << std::endl;
        }
    }

    void SolidworksWriter::WriteFdt(const Dtk_FdtPtr& inFdt)
    {
        auto status = solidworksw::AddEntity(Dtk_EntityPtr::DtkDynamicCast(inFdt));
        if (status != dtkNoError)
        {
            std::cout << "error : " << dtkTypeError(status).c_str() << std::endl;
        }
    }

    Dtk_ErrorStatus SolidworksWriter::OpenPart(const Dtk_string& outputFileName)
    {
        auto status = solidworksw::OpenPart(outputFileName);
        if (status != dtkNoError)
        {
            std::cout << "error : " << dtkTypeError(status).c_str() << std::endl;
        }
        return status;
    }

    void SolidworksWriter::ClosePart()
    {
        solidworksw::ClosePart();
    }

    Dtk_ErrorStatus SolidworksWriter::OpenAssembly(const Dtk_string& outputFileName)
    {
        auto status = solidworksw::OpenAssembly(outputFileName);
        if (status != dtkNoError)
        {
            std::cout << "error : " << dtkTypeError(status).c_str() << std::endl;
        }
        return status;
    }

    void SolidworksWriter::CloseAssembly()
    {
        solidworksw::CloseAssembly();
    }
}